package com.qilin.hammer;



import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.SQLException;

import java.sql.Statement;

 

public class FloatMaxDetect {

    private static String url = "jdbc:mysql://10.111.3.116:3306/test";

    private static String user = "root";

    private static String password = "123456";

    private static int truncateError = 1264;

    

    private static String createTable = "CREATE TABLE test_float(id BIGINT AUTO_INCREMENT PRIMARY KEY, VALUE FLOAT)";

    private static String dropTable = "drop table if exists test_float";

    private static String insertFloat = "insert into test_float (value) value (?)";

    private static String selectFloat = "";

    

    public static void main(String[] args) throws Exception{

       float result = calculateMaxFloatValue(getConnection());

       System.out.print(result);

    }

    

    public static float calculateMaxFloatValue(Connection connection) throws SQLException {

       Statement statement = connection.createStatement();

       statement.execute(dropTable);

       statement.execute(createTable);

       

       PreparedStatement insert = connection.prepareStatement(insertFloat);

       

       try {

           insert.setFloat(1, Float.MAX_VALUE);

           insert.execute();

           // the max value of Java is supported

           return Float.MAX_VALUE;

       } catch (SQLException exp) {

           int errorCode = exp.getErrorCode();

           if (errorCode != truncateError) {

              throw new RuntimeException(exp);

           }

       }

       

       long count = 0;

       

       float high = Float.MAX_VALUE;

       float low = 0;

       float middle = high;

       float last_successful = 0;
       boolean success = true;
       
       while(true) {
         count ++;
         try {
              insert.setFloat(1, middle);
              insert.execute();
            
              // success, need to increase tested value            
              last_successful = middle;
              success = true;             
              low = middle;
              middle = (float)(((double)high + (double)low)/2);

           } catch (SQLException exp) {
              int errorCode = exp.getErrorCode();
              if (errorCode != truncateError) {
                  throw new RuntimeException(exp);
              }
          
              if (!success) {
                  // failed consecutively, assume last successful value is the result. 
                  break;
              }
            
              // fail, need to decrease tested value
              success = false;            
              high = middle;
              middle = (float)(((double)high + (double)low)/2);
           }
           if (middle == last_successful) {
              break;
           }
           if (count % 100 == 0) {
              System.out.println("Current " + last_successful + ", iterations " + count);
           }

       }

       

       System.out.println("Total " + count + " iterations.");

       return last_successful;

       

    }

    

    public static Connection getConnection() throws SQLException {

       Connection connection = DriverManager.getConnection(url, user, password);

       return connection;

    }

}

